home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 June: Reference Library / Dev.CD Jun 00 RL Disk 1.toast / pc / technical documentation / develop / develop issue 23 / develop issue 23 code / projectdrag 1.1b8.sea / ProjectDrag 1.1b8 / Sources / ProjectDrag Sources / PDUtilities.c / PDUtilities.c
Encoding:
C/C++ Source or Header  |  1995-09-07  |  11.4 KB  |  465 lines  |  [TEXT/MPS ]

  1. /* PDUtilities.c: Utility routines for ProjectDrag
  2.  *
  3.  * A set of applets for drag and drop source control by Tim Maroney.
  4.  * See develop, issue 23 for details.
  5.  *
  6.  * Built on DropShell by Leonard Rosenthol, Stephan Somogyi, and Marshall Clow,
  7.  * and using the MoreFiles utilities by Jim Luther.
  8.  *
  9.  * This software is free, but don't modify and redistribute it without
  10.  * changing the status window to indicate your name and your changes!
  11.  */
  12.  
  13. #include <Errors.h>
  14. #include <Folders.h>
  15. #include <Resources.h>
  16. #include <Script.h>
  17. #include <Dialogs.h>
  18. #include <ToolUtils.h>
  19. #include <Finder.h>
  20.  
  21. #include "PDUtilities.h"
  22. #include "MoreFilesExtras.h"
  23. #include "DSUtils.h"
  24.  
  25.  
  26. /* utility routine to find (and create if necesssary) the ProjectDrag
  27.  * Preferences folder inside the System Folder's Preferences folder
  28.  */
  29.  
  30. OSErr FindPreferencesFolder(short *vRefNum, long *folderID)
  31. {
  32.     OSErr err = noErr;
  33.     FSSpec ourFolder;
  34.     Boolean isFolder;
  35.     
  36.     err = FindFolder (kOnSystemDisk, kPreferencesFolderType, true, &ourFolder.vRefNum, &ourFolder.parID);
  37.     if (err != noErr)
  38.         return err;
  39.     GetIndString(ourFolder.name, kProjectDragStrings, kPrefsFolderName);
  40.     err = DirIDFromFSSpec(&ourFolder, folderID, &isFolder);
  41.     if (err == dirNFErr || err == fnfErr)
  42.         err = FSpDirCreate(&ourFolder, smSystemScript, folderID);
  43.     else if (!isFolder)
  44.         err = dirNFErr; /* isn't there an isAFileErr? */
  45.     if (err == noErr)
  46.         *vRefNum = ourFolder.vRefNum;
  47.     return err;
  48. }
  49.  
  50.  
  51. void AppendString(unsigned char *original, unsigned char *append)
  52.     // append one Pascal string to another
  53. {
  54.     int length;
  55.     if (original == 0 || append == 0) return;
  56.     length = append[0];
  57.     if (original[0] + length > 255)
  58.         length = 255 - original[0];
  59.     if (length == 0) return;
  60.     BlockMove(append + 1, original + original[0] + 1, length);
  61.     original[0] += length;
  62. }
  63.  
  64.  
  65. OSErr ProcessFileOrFolder(FSSpec *spec, void (*doFile)(FSSpec *spec, Boolean doingFolder),
  66.                          OSErr (*doFolder)(short vRefNum, long folderID,
  67.                                            void (*doFile)(FSSpec *spec, Boolean doingFolder)))
  68. {
  69.     if (spec->name[0] == 0)
  70.     {
  71.         return (*doFolder)(spec->vRefNum, spec->parID, doFile);
  72.     }
  73.     else
  74.     {
  75.         CInfoPBRec pb;
  76.         
  77.         pb.hFileInfo.ioVRefNum = spec->vRefNum;
  78.         pb.hFileInfo.ioDirID = spec->parID;
  79.         pb.hFileInfo.ioNamePtr = spec->name;
  80.         pb.hFileInfo.ioFDirIndex = (spec->name[0] == 0) ? -1 : 0;
  81.         PBGetCatInfoSync(&pb);
  82.         if (pb.hFileInfo.ioResult != noErr) return pb.hFileInfo.ioResult;
  83.         if ((pb.hFileInfo.ioFlAttrib & 0x10) == 0)
  84.             (*doFile)(spec, false);
  85.         else
  86.             (*doFolder)(spec->vRefNum, pb.dirInfo.ioDrDirID, doFile);
  87.     }
  88.     return noErr;
  89. }
  90.  
  91.  
  92. OSErr ProcessFolder(short vRefNum, long folderID, void (*doFile)(FSSpec *spec, Boolean doingFolder))
  93. {
  94.     CInfoPBRec pb;
  95.     OSErr err = noErr;
  96.     
  97.     /* for all the items in the folder */
  98.     for (pb.hFileInfo.ioFDirIndex = 1; err == noErr && !gDone; pb.hFileInfo.ioFDirIndex++)
  99.     {
  100.         FSSpec spec;
  101.         Boolean isFile;
  102.  
  103.         spec.name[0] = 0;
  104.         pb.hFileInfo.ioNamePtr = spec.name;
  105.         pb.hFileInfo.ioVRefNum = vRefNum;
  106.         pb.hFileInfo.ioDirID = folderID;
  107.         err = PBGetCatInfoSync(&pb);
  108.         if (err != noErr) break;
  109.         
  110.         isFile = ((pb.hFileInfo.ioFlAttrib & 0x10) == 0);
  111.         
  112.         if (isFile)
  113.         {
  114.             spec.vRefNum = vRefNum;
  115.             spec.parID = folderID;
  116.             (*doFile)(&spec, true);
  117.         }
  118.         else
  119.         {
  120.             ProcessFolder(vRefNum, pb.dirInfo.ioDrDirID, doFile);
  121.         }
  122.     }
  123.     if (err == fnfErr)
  124.         err = noErr; /* end of loop */
  125.     return err;
  126. }
  127.  
  128.  
  129. OSErr MakeFullPathName(FSSpec *spec, Str255 fullPathName)
  130. {
  131.     CInfoPBRec pb;
  132.     OSErr err = noErr;
  133.     short vRefNum = spec->vRefNum;
  134.     long folderID = spec->parID;
  135.     
  136.     if (spec->name[0] == 0)
  137.         fullPathName[0] = 0;
  138.     else
  139.         BlockMove(spec->name, fullPathName, spec->name[0] + 1);
  140.     
  141.     do
  142.     {
  143.         Str31 folderName;
  144.  
  145.         folderName[0] = 0;
  146.         pb.hFileInfo.ioNamePtr = folderName;
  147.         pb.hFileInfo.ioVRefNum = vRefNum;
  148.         pb.hFileInfo.ioDirID = folderID;
  149.         pb.hFileInfo.ioFDirIndex = -1;
  150.         err = PBGetCatInfoSync(&pb);
  151.         if (err == noErr)
  152.         {
  153.             if (fullPathName[0] > 0)
  154.                 BlockMove(fullPathName + 1, fullPathName + 2 + folderName[0], fullPathName[0]);
  155.             BlockMove(folderName + 1, fullPathName + 1, folderName[0]);
  156.             fullPathName[folderName[0] + 1] = ':';
  157.             fullPathName[0] += folderName[0] + 1;
  158.             folderID = pb.dirInfo.ioDrParID;
  159.         }
  160.     } while (err == noErr && folderID != fsRtParID);
  161.     return err;
  162. }
  163.  
  164.  
  165. OSErr ExtractCKID(FSSpec *file, CKIDHandle *theCKID)
  166. {
  167.     /* open the resource file */
  168.     short refNum = FSpOpenResFile(file, fsRdPerm);
  169.     if (refNum < 0)
  170.         return ResError();
  171.     
  172.     /* get the CKID from it and clone it */
  173.     *theCKID = (CKIDHandle) Get1IndResource('ckid', 1);
  174.     if (*theCKID == NULL)
  175.     {
  176.         CloseResFile(refNum);
  177.         return resNotFound;
  178.     }
  179.     DetachResource((Handle)*theCKID);
  180.     
  181.     /* close the resource file */
  182.     CloseResFile(refNum);
  183.     return noErr;
  184. }
  185.  
  186. static Boolean IsCommandKey(EventRecord *event)
  187. {
  188.     return (event->what == keyDown) && ((event->modifiers & cmdKey) != 0);
  189. }
  190.  
  191. pascal Boolean ProjectDragIdleProc(EventRecord *theEvent, long *sleepTime, RgnHandle *mouseRgn)
  192. {
  193.     if (theEvent->what == nullEvent)
  194.     {
  195.         *mouseRgn = NULL;
  196.         *sleepTime = 10;
  197.     }
  198.     else if (!IsCommandKey(theEvent) && IsDialogEvent(theEvent))
  199.     {
  200.         DialogPtr dialog;
  201.         short itemHit;
  202.         
  203.         DialogSelect(theEvent, &dialog, &itemHit);
  204.     }
  205.     return false;
  206. }
  207.  
  208.  
  209. short ReplaceString(Handle baseText, StringPtr key, StringPtr substitutionText)
  210. {
  211.     OSErr err = noErr;
  212.     Handle h = NULL;
  213.     
  214.     err = PtrToHand(substitutionText + 1, &h, substitutionText[0]);
  215.     if (err != noErr) return err;
  216.     err = ReplaceText(baseText, h, key);
  217.     DisposeHandle(h);
  218.     return err;
  219. }
  220.  
  221.  
  222. void ReplaceInIndString(StringPtr stringOut, short strListID, short strIndex,
  223.                         StringPtr param1, StringPtr param2,
  224.                         StringPtr param3, StringPtr param4)
  225. {
  226.     Handle h;
  227.     OSErr err;
  228.     
  229.     GetIndString(stringOut, strListID, strIndex);
  230.     err = PtrToHand(stringOut + 1, &h, stringOut[0]);
  231.     if (param1 != NULL)
  232.         err = ReplaceString(h, "\p<1>", param1);
  233.     else
  234.         err = ReplaceString(h, "\p<1>", "\p");
  235.     if (param2 != NULL)
  236.         err = ReplaceString(h, "\p<2>", param2);
  237.     else
  238.         err = ReplaceString(h, "\p<2>", "\p");
  239.     if (param3 != NULL)
  240.         err = ReplaceString(h, "\p<3>", param3);
  241.     else
  242.         err = ReplaceString(h, "\p<3>", "\p");
  243.     if (param4 != NULL)
  244.         err = ReplaceString(h, "\p<4>", param4);
  245.     else
  246.         err = ReplaceString(h, "\p<4>", "\p");
  247.     stringOut[0] = GetHandleSize(h);
  248.     BlockMoveData(*h, stringOut + 1, stringOut[0]);
  249.     DisposeHandle(h);
  250. }
  251.  
  252.  
  253. long LineSize(StringPtr theLine, long maxSize)
  254. {
  255.     long length;
  256.     for (length = 0; maxSize > 0; theLine++, maxSize--)
  257.     {
  258.         length++;
  259.         if (*theLine == '\n') break; /* after incrementing the length to include this */
  260.     }
  261.     return length;
  262. }
  263.  
  264.  
  265. Boolean MatchLineUntilChar(StringPtr line1, long len1, StringPtr line2, long len2, char untilChar)
  266. {
  267.     long i, j;
  268.         
  269.     for (i = j = 0; i < len1 && j < len2; )
  270.     {
  271.         if (untilChar != 0 && line2[j] == untilChar)
  272.             return true; /* we reached the stop character */
  273.             
  274.         if (line1[i] == '\n' || line2[j] == '\n')
  275.         {
  276.             /* if we reach the end of line on one, we must reach it on the other */
  277.             return line1[i] == '\n' && line2[j] == '\n';
  278.         }
  279.         else if (line1[i] == ' ' || line1[i] == '\t')
  280.         {
  281.             /* any amount of white space matches any other */
  282.             if (line2[j] != ' ' && line2[j] != '\t')
  283.                 return false;
  284.             i++, j++; /* we know these characters are blanks */
  285.             while (i < len1 && line1[i] == ' ' || line1[i] == '\t')
  286.                 i++;
  287.             while (j < len2 && line2[j] == ' ' || line2[j] == '\t')
  288.                 j++;
  289.         }
  290.         else if (line1[i] != line2[j])
  291.         {
  292.             return false;
  293.         }
  294.         else /* still matching, go on to next character */
  295.         {
  296.             i++, j++; /* this is here instead of in "for" because
  297.                        * these variables get changed internally
  298.                        */
  299.         }
  300.     }
  301.     
  302.     /* if we get here, all characters should have been exhausted (as am I);
  303.      * the only exception is that one may still have an unexhausted end of line...
  304.      */
  305.     return (len1 == i || (len1 == i + 1 && line1[i] == '\n'))
  306.             && (len2 == j || (len2 == j + 1 && line2[j] == '\n'));
  307. }
  308.  
  309.  
  310. Boolean MatchLine(StringPtr line1, long len1, StringPtr line2, long len2)
  311. {
  312.     return MatchLineUntilChar(line1, len1, line2, len2, 0);
  313. }
  314.  
  315.  
  316. OSErr GetFileData(FSSpec *file, Handle *fileData, short *refNum)
  317. {
  318.     OSErr err;
  319.     IOParam io;
  320.     long count;
  321.     
  322.     *fileData = NULL;
  323.     *refNum = -1;
  324.     
  325.     err = FSpOpenDF(file, fsRdWrPerm, refNum);
  326.     if (err != noErr) goto ErrorExit;
  327.     err = GetEOF(*refNum, &count);
  328.     if (err != noErr) goto ErrorExit;
  329.     *fileData = TempNewHandle(count, &err);
  330.     if (err != noErr) goto ErrorExit;
  331.     HLock(*fileData);
  332.     io.ioCompletion = NULL;
  333.     io.ioRefNum = *refNum;
  334.     io.ioBuffer = **fileData;
  335.     io.ioReqCount = count;
  336.     io.ioPosMode = fsFromStart;
  337.     io.ioPosOffset = 0;
  338.     PBReadAsync((ParmBlkPtr)&io);
  339.     while (io.ioResult == 1)
  340.     {
  341.         EventRecord event;
  342.         WaitNextEvent(everyEvent, &event, 10, NULL);
  343.     }
  344.     err = io.ioResult;
  345.     if (err != noErr) goto ErrorExit;
  346.     HUnlock(*fileData);
  347.     return noErr;
  348.  
  349. ErrorExit:
  350.     if (*refNum != -1)
  351.     {
  352.         FSClose(*refNum);
  353.         *refNum = -1;
  354.     }
  355.     if (*fileData != NULL)
  356.     {
  357.         DisposeHandle(*fileData);
  358.         *fileData = NULL;
  359.     }
  360.     return err;
  361. }
  362.  
  363.  
  364. OSErr WriteFileWithHeader(short refNum, Handle fileData, long startOffset, StringHandle header)
  365. {
  366.     OSErr err = noErr;
  367.     Byte state;
  368.     IOParam io;
  369.     
  370.     /* zero the file */
  371.     err = SetEOF(refNum, 0);
  372.     if (err != noErr) return err;
  373.     err = SetFPos(refNum, fsFromStart, 0);
  374.     if (err != noErr) return err;
  375.     
  376.     /* write out the header to the file */
  377.     if (header != NULL)
  378.     {
  379.         state = HGetState(header);
  380.         HLock(header);
  381.         io.ioCompletion = NULL;
  382.         io.ioRefNum = refNum;
  383.         io.ioBuffer = *header;
  384.         io.ioReqCount = GetHandleSize(header);
  385.         io.ioPosMode = fsFromStart;
  386.         io.ioPosOffset = 0;
  387.         PBWriteAsync((ParmBlkPtr)&io);
  388.         while (io.ioResult == 1)
  389.         {
  390.             EventRecord event;
  391.             WaitNextEvent(everyEvent, &event, 10, NULL);
  392.         }
  393.         err = io.ioResult;
  394.         HSetState(header, state);
  395.         if (err != noErr) return err;
  396.     }
  397.     
  398.     /* copy the data fork from the start offset to the file */
  399.     state = HGetState(fileData);
  400.     HLock(fileData);
  401.     io.ioCompletion = NULL;
  402.     io.ioRefNum = refNum;
  403.     io.ioBuffer = (*fileData) + startOffset;
  404.     io.ioReqCount = GetHandleSize(fileData) - startOffset;
  405.     io.ioPosMode = fsFromStart;
  406.     io.ioPosOffset = GetHandleSize(header);
  407.     PBWriteAsync((ParmBlkPtr)&io);
  408.     while (io.ioResult == 1)
  409.     {
  410.         EventRecord event;
  411.         WaitNextEvent(everyEvent, &event, 10, NULL);
  412.     }
  413.     err = io.ioResult;
  414.     HSetState(fileData, state);
  415.     if (err != noErr) return err;
  416.     
  417.     return noErr;
  418. }
  419.  
  420.  
  421. /* SetFileLabel was cribbed from ChangeFDFlags in MoreFilesExtras.c */
  422.  
  423. OSErr SetFileLabel(FSSpec *file, short label, short *oldLabel)
  424. {
  425.     CInfoPBRec pb;
  426.     OSErr err;
  427.     short realVRefNum;
  428.     long parID;
  429.  
  430.     if (file->name[0] == 0)
  431.         pb.hFileInfo.ioNamePtr = NULL;
  432.     else
  433.         pb.hFileInfo.ioNamePtr = file->name;
  434.     pb.hFileInfo.ioVRefNum = file->vRefNum;
  435.     pb.hFileInfo.ioDirID = file->parID;
  436.     pb.hFileInfo.ioFDirIndex = 0;    /* use ioNamePtr and ioDirID */
  437.     err = PBGetCatInfoSync(&pb);
  438.     if ( err == noErr )
  439.     {
  440.         parID = pb.hFileInfo.ioFlParID;    /* save parent dirID for BumpDate call */
  441.  
  442.         if (oldLabel != NULL)
  443.             *oldLabel = (pb.hFileInfo.ioFlFndrInfo.fdFlags >> 1) & kColor;
  444.  
  445.         pb.hFileInfo.ioFlFndrInfo.fdFlags &= ~kColor; /* clear the bits */
  446.         pb.hFileInfo.ioFlFndrInfo.fdFlags |= (label << 1) & kColor; /* set the bits */
  447.     
  448.         pb.hFileInfo.ioDirID = file->parID;
  449.         err = PBSetCatInfoSync(&pb);    /* now, save the new information back to disk */
  450.  
  451.         if ( (err == noErr) && (parID != fsRtParID) ) /* can't bump fsRtParID */
  452.         {
  453.             /* get the real vRefNum in case a full pathname was passed */
  454.             err = DetermineVRefNum((StringPtr)file->name, file->vRefNum, &realVRefNum);
  455.             if ( err == noErr )
  456.             {
  457.                 err = BumpDate(realVRefNum, parID, NULL);
  458.                     /* and bump the parent directory's mod date to wake up the Finder */
  459.                     /* to the change we just made */
  460.             }
  461.         }
  462.     }
  463.     return ( err );
  464. }
  465.